// function and dom lib
function $el(tag, children = [], attrs = {}, cls = []) {
    let e = document.createElement(tag)
    for (let k in attrs) {
        let v = attrs[k]
        e.setAttribute(k, v)
    }
    if (typeof children === "string") {
        e.textContent = children
    } else {
        for (let c of children) {
            e.appendChild(c)
        }
    }
    if (typeof cls === "string") {
        e.classList.add(cls)
    } else {
        for (let c of cls) {
            e.classList.add(c)
        }
    }
    return e
}

// logic lib
function toA(number) {
    if (toA[number] !== undefined) {
        return toA[number]
    }
    num_str = ''
    while (number >= 0) {
        i = number % 26
        num_str = String.fromCharCode(i + 65) + num_str
        number = parseInt(number / 26) - 1
    }
    toA[number] = num_str
    return num_str
}
function toA0(col, row) {
    return toA(col) + (row + 1)
}

function ctd(td, t = '') {
    if (td === undefined) {
        td = $el('td')
    }
    td.addEventListener("click", function (event) {

        let t = $(this).data('text')
        theInput.value = t

        $('td').removeClass("cur")
        this.classList.add("cur");
        let that = this
        cur = toA0($(this).index() - 1, $(this.parentNode).index() - 1)

        curtd = this

        // edited
        // $('td').map(function (_, e) {
        //     let [i, j] = getij(e)
        //     if (cur !== toA0(i, j) && $data(e, 'editing')) {
        //         let v = e.querySelector('input').value
        //         $data(e, 'editing', '')
        //         setAndEval(e, v)
        //         data[j][i] = v
        //         saveData()
        //     }
        // })
    })
    // td.addEventListener("dblclick", function (event) {
    //     let t = $data(this, 'text')
    //     theInput.value = t
    //     if (!$data(this, 'editing')) {
    //         $data(this, 'editing', 1)
    //         this.textContent = ''
    //         let ip = $el("input", '', { 'value': t === null ? '' : t })
    //         this.appendChild(ip)
    //         ip.focus()
    //     }
    // })
    return td
}
function getij(td) {
    let j = $(td).index() - 1
    let i = $(td.parentNode).index() - 1
    return [i, j]
}
function initWithData(mat) {
    let n = mat.length
    let m = mat[0].length
    $(theTable).data('row', n)
    $(theTable).data('col', m)
    let tr = tbody.querySelector('tr')
    for (let i = 0; i < m; i++) {
        tr.appendChild($el('td', toA(i), { 'data-i': i }, 'colSel'))
    }
    let i = 0
    for (let row of mat) {
        tr = $el('tr', [$el('td', (i + 1).toString(), { 'data-i': i }, 'rowSel')])
        let j = 0
        for (let e of row) {
            if (e === undefined || e === null) {
                e = ''
            }
            let td = ctd($el('td', e), e)
            setAndEval(td, e, i, j)
            tr.appendChild(td)
            if (i === 0 && j === 0) {
                td.classList.add("cur")
            }
            j++
        }
        tbody.appendChild(tr)
        i++
    }
}
function dataAddRow() {
    let n = data[0].length
    let a = new Array(n)
    a.fill('')
    data.push(a)
}
function dataAddCol() {
    for (let row of data) {
        row.push('')
    }
}
function saveData() {
    localStorage.setItem("table_data", JSON.stringify(data))
}
function loadData() {
    let t = localStorage.getItem("table_data")
    if (!t) {
        return [["Start here"]]
    }
    return JSON.parse(t)
}
function setCur(t) {
    setAndEval(curtd, t)

    let i = $(curtd).index() - 1
    let j = $(curtd.parentNode).index() - 1
    data[j][i] = t
    saveData()
}
function setAndEval(td, t, i, j) {
    $(td).data( 'text', t)
    if (t[0] && t[0] === '=') {
        t = eval(t.substr(1))
    }
    td.textContent = t
    if (i === undefined) {
        [i, j] = getij(td)
    }
    window[toA0(j, i)] = t
}

// init
var theTable = document.getElementById('theTable')
var tbody = theTable.querySelector("tbody")
var theInput = document.getElementById('theInput')
var cur = "A1"
var data = loadData()
initWithData(data)
var curtd = tbody.children[1].children[1]

// dom
// $on('td', "click",)
$('#btnAddRow').on('click', function () {
    dataAddRow()
    let row = parseInt($(theTable).data('row')) + 1
    $(theTable).data('row', row)
    let td = $el('td', row.toString(), { 'data-i': row - 1 }, "rowSel")
    let tds = [td]
    for (let i = 0; i < $(theTable).data('col'); i++) {
        tds.push(ctd())
    }
    tbody.appendChild($el('tr', tds))
})
$('#btnAddCol').on('click', function () {
    dataAddCol()
    let col = parseInt($(theTable).data('col'))
    $(theTable).data('col', col + 1)
    let i = 0
    $('tr').map(function (_, e) {
        if (i === 0) {
            e.appendChild($el('td', toA(col).toString(), { 'data-i': col }, "colSel"))
        } else {
            e.appendChild(ctd())
        }
        i++
    })
})
$(theInput).on('change', function () {
    setCur(theInput.value)
})
$(theInput).on('keyup', function (event) {
    if (event.keyCode === 13) {
        setCur(theInput.value)
    }
})
